#include "Config.h"
#include "Log.h"

#include <iostream>
#include <fstream>
#include <cctype>
#include <sstream>

using std::ifstream;
using std::cout;
using std::cerr;



Config::Config(const string &filename)
{
    parseFile(filename);
}


Config::LogConfig::LogConfig(const Config &cf)
: log_path(cf.getString("LOG_PATH", "logs/log.txt"))
, max_file_size(cf.getLong("MAX_FILE_SIZE", 1024 * 1024 * 10))
, max_file_num(cf.getInt("MAX_FILE_NUM", 5))
{}

string Config::getString(const string &key, const string &default_val) const
{
    auto it = _configMap.find(key);
    return it != _configMap.end() ? it->second : default_val;
}

int Config::getInt(const string &key, int default_val) const
{
    auto it = _configMap.find(key);
    if (it == _configMap.end())
        return default_val;

    try
    {
        if (it->second.find('*') != std::string::npos)
        {
            return evaluate_expression(it->second);
        }
        return std::stoi(it->second);
    }
    catch (...)
    {
        return default_val;
    }
}
long Config::getLong(const string &key, int default_val) const
{
    auto it = _configMap.find(key);
    if (it == _configMap.end())
        return default_val;

    try
    {
        if (it->second.find('*') != std::string::npos)
        {
            return evaluate_expression(it->second);
        }
        return std::stol(it->second);
    }
    catch (...)
    {
        return default_val;
    }
}
bool Config::getBool(const string &key, int default_val) const
{
    auto it = _configMap.find(key);
    if (it == _configMap.end())
        return default_val;

    std::string val = it->second;
    std::transform(val.begin(), val.end(), val.begin(), [](unsigned char c)
                   { return std::tolower(c); });

    if (val == "true" || val == "yes" || val == "1")
        return true;
    if (val == "false" || val == "no" || val == "0")
        return false;
    return default_val;
}

void Config::parseFile(const string &filename)
{
    ifstream ifs(filename);
    if (!ifs.is_open())
    {
        // cerr << "open file " << filename << " error\n";
        // return;
        throw std::runtime_error("Failed to open config file: " + filename);
    }

    string line;
    while (std::getline(ifs, line))
    {
        // 去掉注释行
        size_t commentPos = line.find("#");
        if(commentPos != string::npos)
        {
            line = line.substr(0, commentPos);
            // cout << "line = " << line << "\n";
        }
        if(line.empty()) continue;
        // if (commentPos != string::npos)
        //     continue; // 下一行

        size_t delimiterPos = line.find("=");
        if (delimiterPos == string::npos)
            continue;

        string key = trim(line.substr(0, delimiterPos));
        string val = trim(line.substr(delimiterPos + 1));

        if (!key.empty())
        {
            _configMap[key] = val;
        }
    }
}

string Config::trim(const string &str)
{
    auto start = str.begin();
    while (start != str.end() && std::isspace(*start))
    {
        ++start;
    }
    auto end = str.end();
    do
    {
        --end;
    } while (std::distance(end, start) > 0 && std::isspace(*end));

    return string(start, end + 1);
}

void Config::printConfigMap() const
{
    cout << "configMap begin \n";
    for (auto it = _configMap.begin(); it != _configMap.end(); ++it)
    {
        cout << it->first << " " << it->second << "\n";
    }
    cout << "configMap end \n";
}

int Config::evaluate_expression(const string &expr) const
{
    std::istringstream iss(expr);
    int result = 1;
    int num;
    char op;

    iss >> num;
    result = num;

    while (iss >> op >> num)
    {
        if (op == '*')
        {
            result *= num;
        }
        else if (op == '/')
        {
            if (num == 0)
                throw std::runtime_error("Division by zero");
            result /= num;
        }
        else
        {
            throw std::runtime_error("Unsupported operator");
        }
    }

    return result;
}